package com.luo.d3s.light.jpa.ec.domain.base;

import com.luo.d3s.core.domain.model.Identity;
import com.luo.d3s.core.util.IdGenUtils;
import com.luo.d3s.core.util.validation.Validates;

import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 业务ID（适配JPA嵌套对象）<br/>
 * 注：JPA中组合ID必须重写equals、hashCode方法
 *
 * @author luohq
 * @date 2022-11-27 16:19
 */
@Embeddable
public class BizId implements Identity {

    /**
     * ID值
     */
    @NotNull
    @Positive
    private Long id;

    BizId() {

    }

    BizId(Long id) {
        this.id = id;
        this.validateSelf();
    }

    public Long getId() {
        return id;
    }

    /**
     * 生成新的ID
     *
     * @return 新ID
     */
    public static BizId newBizId() {
        return new BizId(IdGenUtils.nextDigitalId());
    }



    /**
     * 批量转换实体ID为具体值列表
     *
     * @param bizIds 实体ID列表
     * @return 具体值列表
     */
    public static Set<Long> toValues(Collection<BizId> bizIds) {
        Validates.notEmpty(bizIds, "BizId list is empty");
        return bizIds.stream()
                .map(BizId::getId)
                .collect(Collectors.toSet());
    }

    /**
     * 根据ID值转换BizId
     *
     * @param id id长整形值
     * @return 业务ID
     */
    public static BizId fromValue(Long id) {
        return new BizId(id);
    }

    /**
     * 批量转换具体值为实体ID列表
     *
     * @param values 具体值列表
     * @return 实体ID列表
     */
    public static Set<BizId> fromValues(Collection<Long> values) {
        Validates.notEmpty(values, "BizId value list is empty");
        return values.stream()
                .map(BizId::new)
                .collect(Collectors.toSet());
    }

    /**
     * 批量转换具体值为实体ID列表（若values为空则返回空列表）
     *
     * @param values 具体值列表
     * @return 实体ID列表
     */
    public static Set<BizId> fromNullableValues(Collection<Long> values) {
        if (Objects.isNull(values) || values.isEmpty()) {
            return new HashSet<>();
        }
        return values.stream()
                .map(BizId::new)
                .collect(Collectors.toSet());
    }

    @Override
    public String toString() {
        return String.valueOf(this.id);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        BizId bizId = (BizId) o;
        return Objects.equals(id, bizId.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
